package com.art.ai.service.agent.runtime;

import com.art.ai.core.dto.conversation.AiMessageDTO;
import com.art.ai.core.enums.MessageRoleEnum;
import com.art.ai.service.agent.spec.AgentSpec;
import com.art.ai.service.agent.tool.AgentToolDefinition;
import com.art.ai.service.agent.tool.ToolArgumentDescriptor;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Agent Prompt 构建器
 *
 * @author fxz
 * @since 2025-11-01
 */
@Component
public class AgentPromptBuilder {

	public List<ChatMessage> buildPrompt(AgentRuntimeState state, List<AgentToolDefinition> toolDefinitions,
			AgentResponseRoute route) {
		List<ChatMessage> messages = new ArrayList<>();

		boolean isPlanMode = state.getSpec().getStrategy().getType() == AgentSpec.StrategyType.PLAN_EXECUTE;
		boolean expectPlan = isPlanMode && !state.isPlanEstablished();

		SystemMessage systemMessage = SystemMessage
			.from(buildSystemPrompt(state.getSpec(), toolDefinitions, isPlanMode, expectPlan, route));
		messages.add(systemMessage);

		messages.addAll(buildMemoryMessages(state.getMemory()));

		String userContent = buildUserBlock(state, isPlanMode, expectPlan);
		messages.add(UserMessage.from(userContent));

		return messages;
	}

	private String buildSystemPrompt(AgentSpec spec, List<AgentToolDefinition> toolDefinitions, boolean isPlanMode,
			boolean expectPlan, AgentResponseRoute route) {
		List<String> sections = new ArrayList<>();

		// 用户自定义系统提示
		if (StringUtils.isNotBlank(spec.getSystemPrompt())) {
			sections.add(spec.getSystemPrompt().trim());
		}

		// 工具列表
		sections.add(buildToolCatalog(toolDefinitions));

		// 决策格式说明
		sections.add(buildDecisionFormat(isPlanMode, expectPlan, route));

		// 规则说明
		sections.add(buildRules(isPlanMode, expectPlan, route));

		return sections.stream().filter(StringUtils::isNotBlank).collect(Collectors.joining("\n\n"));
	}

	private String buildDecisionFormat(boolean isPlanMode, boolean expectPlan, AgentResponseRoute route) {
		if (route == AgentResponseRoute.FUNCTION_CALL) {
			return buildFunctionCallFormat(isPlanMode, expectPlan);
		}
		return buildJsonFormat(isPlanMode, expectPlan);
	}

	private String buildFunctionCallFormat(boolean isPlanMode, boolean expectPlan) {
		List<String> lines = new ArrayList<>();
		lines.add("可用控制函数：");

		if (isPlanMode) {
			if (expectPlan) {
				lines.add("- agent_plan: 生成执行计划");
				lines.add("  参数: { items: [{ step: 步骤序号, goal: 目标描述, tool?: 工具名称 }] }");
			}
			else {
				lines.add("- agent_final: 返回最终结果");
				lines.add("  参数: { message: 回复内容, requiresUserInput?: 是否需要用户输入 }");
			}
		}
		else {
			lines.add("- agent_final: 返回最终结果");
			lines.add("  参数: { message: 回复内容 }");
		}

		return String.join("\n", lines);
	}

	private String buildJsonFormat(boolean isPlanMode, boolean expectPlan) {
		List<String> lines = new ArrayList<>();
		lines.add("以JSON格式返回决策：");

		if (expectPlan) {
			lines.add("{ \"kind\": \"plan\", \"plan\": [{ \"step\": 1, \"goal\": \"...\", \"tool\": \"...\" }] }");
		}
		else if (isPlanMode) {
			lines.add("{ \"kind\": \"tool_calls\", \"toolCalls\": [{ \"name\": \"...\", \"args\": {...} }] }");
			lines.add("或");
			lines.add("{ \"kind\": \"final\", \"message\": \"...\", \"requiresUserInput\": false }");
		}
		else {
			// REACT模式
			lines.add("{ \"kind\": \"tool_calls\", \"toolCalls\": [{ \"name\": \"...\", \"args\": {...} }] }");
			lines.add("或");
			lines.add("{ \"kind\": \"final\", \"message\": \"...\" }");
		}

		return String.join("\n", lines);
	}

	private String buildRules(boolean isPlanMode, boolean expectPlan, AgentResponseRoute route) {
		List<String> lines = new ArrayList<>();

		if (expectPlan) {
			lines.add("规则：");
			lines.add("1. 当前阶段生成计划，不调用工具");
			lines.add("2. 计划应包含明确的步骤和目标");
			lines.add("3. 每个步骤的goal描述该步骤要达成什么");
		}
		else if (isPlanMode) {
			lines.add("规则：");
			lines.add("1. 根据计划执行当前步骤");
			lines.add("2. 工具调用失败时可重试或跳过");
			lines.add("3. 需要用户输入时设置requiresUserInput=true");
		}
		else {
			// REACT模式
			lines.add("规则：");
			lines.add("1. 需要外部信息时调用工具");
			lines.add("2. 工具返回结果后继续推理");
			lines.add("3. 能够回答用户时返回final");
		}

		return String.join("\n", lines);
	}

	private String buildToolCatalog(List<AgentToolDefinition> toolDefinitions) {
		List<String> lines = new ArrayList<>();
		lines.add("可用工具：");

		if (toolDefinitions == null || toolDefinitions.isEmpty()) {
			lines.add("无");
			return String.join("\n", lines);
		}

		toolDefinitions.forEach(def -> lines.addAll(describeTool(def)));

		return String.join("\n", lines);
	}

	private List<String> describeTool(AgentToolDefinition definition) {
		List<String> lines = new ArrayList<>();
		String description = StringUtils.defaultIfBlank(definition.getDescription(), "");
		if (StringUtils.isNotBlank(description)) {
			lines.add("- " + definition.getName() + ": " + description);
		}
		else {
			lines.add("- " + definition.getName());
		}
		if (definition.getArguments() != null && !definition.getArguments().isEmpty()) {
			lines.add("  参数：");
			definition.getArguments().forEach(arg -> lines.add(formatToolArgument(arg)));
		}
		return lines;
	}

	private String formatToolArgument(ToolArgumentDescriptor arg) {
		StringBuilder line = new StringBuilder("    - ");
		line.append(arg.getName()).append(" (").append(StringUtils.defaultString(arg.getType(), "string"));
		line.append(arg.isRequired() ? ", 必填" : ", 可选").append(")");
		if (StringUtils.isNotBlank(arg.getDescription())) {
			line.append(": ").append(arg.getDescription());
		}
		return line.toString();
	}

	private List<ChatMessage> buildMemoryMessages(List<AiMessageDTO> history) {
		List<ChatMessage> messages = new ArrayList<>();
		if (history == null) {
			return messages;
		}
		history.forEach(message -> {
			if (StringUtils.isBlank(message.getContent())) {
				return;
			}
			MessageRoleEnum role = MessageRoleEnum.fromCode(message.getRole());
			switch (role) {
				case USER -> messages.add(UserMessage.from(message.getContent()));
				case ASSISTANT -> messages.add(AiMessage.from(message.getContent()));
				case SYSTEM -> messages.add(SystemMessage.from(message.getContent()));
				default -> {
				}
			}
		});
		return messages;
	}

	private String buildUserBlock(AgentRuntimeState state, boolean isPlanMode, boolean expectPlan) {
		StringBuilder sb = new StringBuilder();

		sb.append("用户请求：\n").append(state.getUserInput()).append("\n\n");

		// 仅PLAN模式显示计划信息
		if (isPlanMode && state.isPlanEstablished()) {
			sb.append("执行计划：\n");
			sb.append(state.unmodifiablePlan()
				.stream()
				.map(item -> String.format("%d. [%s] %s", item.getStep(), item.getStatus().name(),
						StringUtils.defaultString(item.getGoal())))
				.collect(Collectors.joining("\n")));
			sb.append("\n\n");

			AgentPlanItem activeItem = state.getActivePlanItem();
			if (activeItem != null) {
				sb.append("当前步骤：").append(activeItem.getStep()).append(". ").append(activeItem.getGoal());
				sb.append("\n\n");
			}
		}

		// 历史步骤
		if (!state.getSteps().isEmpty()) {
			sb.append("历史执行：\n");
			state.getSteps().forEach(step -> {
				if (!step.getToolCalls().isEmpty()) {
					step.getToolCalls()
						.forEach(call -> sb.append("工具: ")
							.append(call.getName())
							.append("\n结果: ")
							.append(step.getObservation().getOrDefault(call.getName(), ""))
							.append("\n"));
				}
			});
			sb.append("\n");
		}

		if (expectPlan) {
			sb.append("请生成执行计划");
		}
		else {
			sb.append("请继续执行");
		}

		return sb.toString();
	}

}
